home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / src / lpc10 / Options / voice_nn.c < prev   
C/C++ Source or Header  |  2000-05-18  |  10KB  |  260 lines

  1. /* SpeedEdit 184,196,24,0,0,10,16,10 Updated 08/10/92 09:10:50 */
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include "filter.h"
  5.  
  6. #define NFEATURE    3        /* number of features per voicing frame */
  7. #define NICLASS        3*NFEATURE    /* number of inputs to the neural net classifier */
  8. #define LPF_LENG    3        /* length of low pass filter used to estimate average v & uv energy */
  9. #define MAXDB        72.25        /* scale factor to normalize speech level */
  10.                     /* 20.0*log10(4096), where 4096 = max signal amplitude */
  11. #define V_NOMINAL    0.6        /* nominal value of Elow_v_hat */
  12. #define UV_NOMINAL    0.3        /* nominal value of Elow_uv_hat */
  13. #define NFRAMES_ELOW    440        /* number of (half) frames of Elow history to save */
  14. #define BUF_FRACT    .1        /* fraction of Elow_buf used to determine El and Eh */
  15. #define THRESH        .2        /* threshhold for Eh - El to declare speech present in Elow_buf */
  16. #define NHIDDEN        2        /* number of hidden units used in the neural net classifier */
  17.  
  18. /*     ----------------------------------------  CLASSIFY  ----------------------------------------
  19. */
  20.  
  21. static float classify(x)
  22.  
  23. float x[];
  24.  
  25. {
  26.    int i;
  27.    float out[NHIDDEN+1];
  28.    static float bias[] =    {     4.7605e-01, -4.4143e-01, -2.5532e+01    };
  29.    static float weight0[] = {     0.0000e+00,  9.9600e+00,  1.3399e+00    };    /* weight0[0] is not used */
  30.    static float weight1[] = {     2.5327e-01,  5.1214e-02,  5.1845e-02,
  31.                  8.7389e-01,  6.6049e-02,  5.6143e-02,
  32.                  2.1496e-02,  6.4269e-02,  7.5030e-03    };
  33.    static float weight2[] = {     9.1907e-01,  1.4349e+00, -5.3130e-03,
  34.                 -2.1947e+00,  2.5551e+01,  4.0398e-01,
  35.                 -1.9285e-01, -9.4621e-01,  7.7245e-01    };
  36.  
  37.    /*   hidden unit 1   */
  38.    out[1] = bias[1];
  39.    for (i=0; i<NICLASS; i++) out[1] += weight1[i] * x[i];
  40.    out[1] = tanh((double) out[1]);
  41.  
  42.    /*   hidden unit 2   */
  43.    out[2] = bias[2];
  44.    for (i=0; i<NICLASS; i++) out[2] += weight2[i] * x[i];
  45.    out[2] = tanh((double) out[2]);
  46.  
  47.    /*   output unit   */
  48.    out[0] = bias[0];
  49.    for (i=1; i<=NHIDDEN; i++) out[0] += weight0[i] * out[i];
  50.  
  51.    return tanh((double) out[0]);
  52. }
  53.  
  54. /*     ----------------------------------------  AUTOCOR  ----------------------------------------
  55. */
  56.  
  57. static float autocor(signal, n, lag)
  58.  
  59. float signal[];
  60. int n, lag;
  61.  
  62. {
  63.    int i, p1, p2;
  64.    float cor1, cor2, cor3;
  65.  
  66.    /*p1 = lag / 2;                /* to be centered in signal window, go back half of lag */
  67.    p1 = lag >> 1;                /* to be centered in signal window, go back half of lag */
  68.    p2 = lag - p1;                /* and forward the difference */
  69.    cor1 = cor2 = cor3 = 0.0;
  70.    for (i=0; i<n;  i++)
  71.    {
  72.       cor1 += signal[i-p1] * signal[i+p2];
  73.       cor2 += signal[i-p1] * signal[i-p1];
  74.       cor3 += signal[i+p2] * signal[i+p2];
  75.    }
  76.    if (cor2 == 0.0 || cor3 == 0.0) return 0.0;
  77.    else                            return (cor1 * cor1) / (cor2 * cor3);    /* range:  0 to +1 */
  78. }
  79.  
  80. /*     ----------------------------------------  SINSERT  ----------------------------------------
  81.  
  82.      This routine re-sorts a buffer which has a single (new) entry (perhaps) out of place.
  83. 'sbuf' is the array sorted in ascending order; 'obuf' is another array to be re-ordered in the same manner;
  84. 'k' is the index of the newly inserted entry.
  85. */
  86.  
  87. static void sinsert(sbuf, obuf, n, k)
  88.  
  89. float sbuf[];                            /*  sbuf[0:n-1]  */
  90. int obuf[], n, k;                        /*  obuf[0:n-1]  */
  91.  
  92. {
  93.    int i, j, tempi;
  94.    float temp;
  95.  
  96.    if (k < n-1 && sbuf[k] > sbuf[k+1])                /* is new datum inserted too low in buffer? */
  97.    {
  98.       for (i=k+2; i<n; i++) if (sbuf[k] <= sbuf[i]) break;    /* i points to value to follow sbuf[k] */
  99.       temp  = sbuf[k];
  100.       tempi = obuf[k];
  101.       for (j=k; j<i-1; j++)
  102.       {
  103.          sbuf[j] = sbuf[j+1];
  104.          obuf[j] = obuf[j+1];
  105.       }
  106.       sbuf[i-1] = temp;
  107.       obuf[i-1] = tempi;
  108.    }
  109.    else if (k > 0 && sbuf[k] < sbuf[k-1])            /* is new datum inserted too high in buffer? */
  110.    {
  111.       for (i=k-2; i>=0; i--) if (sbuf[k] >= sbuf[i]) break;    /* i points to value to precede sbuf[k] */
  112.       temp  = sbuf[k];
  113.       tempi = obuf[k];
  114.       for (j=k; j>i+1; j--)
  115.       {
  116.          sbuf[j] = sbuf[j-1];
  117.          obuf[j] = obuf[j-1];
  118.       }
  119.       sbuf[i+1] = temp;
  120.       obuf[i+1] = tempi;
  121.    }
  122. }
  123.  
  124. /*     ----------------------------------------  VFEATURES  ----------------------------------------
  125. */
  126.  
  127. static void vfeatures(speech, lpspeech, length, pitch, features)
  128.  
  129. float speech[], lpspeech[], features[];                /* all indices start at 0 */
  130. int length, pitch;
  131.  
  132. {
  133.    int i, nframes;
  134.    float Elow, Elown, Flow, Cpch;
  135.    float ss_low, ss_full, temp, El, Eh, Ethresh;
  136.  
  137.    static int first = 1;                /* flag to indicate first execution of this routine */
  138.    static int indx = 0;
  139.    static float Elow_uv_hat;                /* estimate of average Elow when speech is absent */
  140.    static float Elow_v_hat;                /* estimate of average Elow when speech is present  */
  141.    static float avg_num[] = { 1.60283e-4, 3.20566e-4, 1.60283e-4 };
  142.    static float avg_den[] = { 1.0,       -1.949359,   0.95 };
  143.    static float Elow_buf[NFRAMES_ELOW];            /* the past NFRAMES_ELOW of Elow values */
  144.    static int Elow_order[NFRAMES_ELOW];
  145.    static FILTER *uvnf, *vnf;
  146.    static float uvnf_state[] = { 468.053, 468.053 };
  147.    static float  vnf_state[] = { 936.107, 936.107 };
  148.  
  149.    if (first)                            /* initialize on first pass */
  150.    {
  151.       first = 0;
  152.  
  153.       /*   create the two filters used to estimate Elow when speech absent and present   */
  154.       uvnf = filter_create(avg_num, LPF_LENG, avg_den, LPF_LENG);
  155.       vnf  = filter_create(avg_num, LPF_LENG, avg_den, LPF_LENG);
  156.  
  157.       /*   get the averaging filter outputs to nominal values   */
  158.       filter_state_set(uvnf, 2, uvnf_state);
  159.       filter_state_set( vnf, 2,  vnf_state);
  160.       Elow_v_hat  = filter(vnf,   V_NOMINAL);
  161.       Elow_uv_hat = filter(uvnf, UV_NOMINAL);
  162.  
  163.       /*   initialize Elow_buf to nominal values   */
  164.       for (i=0; i<NFRAMES_ELOW; i++)
  165.       {
  166.          if (i < .5 * NFRAMES_ELOW) Elow_buf[i] = UV_NOMINAL;
  167.          else                Elow_buf[i] = V_NOMINAL;
  168.          Elow_order[i] = i;
  169.       }
  170.    }
  171.  
  172.    /*   Elow:  low band energy   */
  173.    ss_low = 0.0;
  174.    for (i=0; i<length;  i++) ss_low += lpspeech[i] * lpspeech[i];
  175.    Elow = ss_low / length;
  176.    if (Elow > 0.0) Elow = 10.0 * log10((double) Elow) - MAXDB;    /* convert to dB; fully loaded = 0 dB */
  177.    else            Elow = -100.0;                /* -100 dB if zero input */
  178.    if (Elow < -100.0) Elow = -100.0;                /* clamp negative end of range */
  179.    /*Elow = (Elow / 50.0) + 1.0;                    /* -100 dB to 0 dB is scaled -1.0 to +1.0 */
  180.    Elow = (Elow * 20e-3) + 1.0;                    /* -100 dB to 0 dB is scaled -1.0 to +1.0 */
  181.  
  182.    /*   Determine the average speaking level   */
  183.    for (i=0; i<NFRAMES_ELOW; i++) if (Elow_order[i] == indx) break;    /* i = index of oldest Elow_buf sample */
  184.    Elow_buf[i] = Elow;                        /* replace oldest sample with newest */
  185.    sinsert(Elow_buf, Elow_order, NFRAMES_ELOW, i);        /* re-sort buffers after insertion at index i */
  186. /**   indx = ++indx % NFRAMES_ELOW;                /* increment indx modulo NFRAMES_ELOW */
  187.    indx++;
  188.    if(indx == NFRAMES_ELOW) indx = 0;
  189.    El = Eh = 0.0;
  190.    nframes = BUF_FRACT * NFRAMES_ELOW;
  191.    for (i=0; i<nframes; i++)
  192.    {
  193.       El += Elow_buf[i];                    /* sum the lowest  BUF_FRACT of Elow_buf */
  194.       Eh += Elow_buf[NFRAMES_ELOW-1 - i];            /* sum the highest BUF_FRACT of Elow_buf */
  195.    }
  196.    /*El /= nframes;*/
  197.    El *= 0.02272727272;
  198.    /*Eh /= nframes;*/
  199.    Eh *= 0.02272727272;
  200.    if (Eh - El > THRESH) Ethresh = .5 * (El + Eh);        /* if it's likely that Elow_buf has speech */
  201.    else             Ethresh = .5 * (Elow_v_hat + Elow_uv_hat);
  202.    if (Elow > Ethresh) Elow_v_hat  = filter( vnf, Elow);    /* speech present this half-frame */
  203.    else               Elow_uv_hat = filter(uvnf, Elow);    /* speech absent  this half-frame */
  204.  
  205.    /*   Elown:  Elow normalized   */
  206.    Elown = Elow - Elow_v_hat + V_NOMINAL;
  207.  
  208.    /*   Flow:  fraction of full band energy in low band   */
  209.    ss_full = 0.0;
  210.    for (i=0; i<length;  i++) ss_full += speech[i] * speech[i];
  211.    if (ss_full > 0.0) Flow = ss_low / ss_full;
  212.    else               Flow = 0.0;
  213.    if (Flow > 1.0) Flow = 1.0;                    /* this happens quite often! */
  214.    Flow = 2.0 * Flow - 1.0;                    /* range: -1 to +1 */
  215.  
  216.    /*   Cpch:  autocorrelation of LPF(speech) @ one pitch period   */
  217.    Cpch = -2.0;
  218.    for (i=-1; i<=1; i++)
  219.    {
  220.       temp = 2.0 * autocor(lpspeech, length, pitch+i) - 1.0;    /* range: -1 to +1 */
  221.       if (temp > Cpch) Cpch = temp;
  222.    }
  223.  
  224.    features[0] = Elown;
  225.    features[1] = Flow;
  226.    features[2] = Cpch;
  227. }
  228.  
  229. /*     ----------------------------------------  VOICING  ----------------------------------------
  230.  
  231. Determines two half-frame voicing decisions for the frame speech[start:end].
  232. */
  233.  
  234. void voicing(speech, lpspeech, start, end, pitch, v1, v2)
  235. float speech[], lpspeech[];
  236. int start, end, pitch, *v1, *v2;
  237. {
  238.    int i, vfleng;
  239.    float vclass;
  240.    static float fbuf[4*NFEATURE] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  241.  
  242.    /* shift the feature buffer by two voicing frames */
  243.    for (i=0; i<2*NFEATURE; i++) fbuf[i] = fbuf[i + 2*NFEATURE];
  244.  
  245.    /*vfleng = (end - start + 1) / 2;                /* voicing frame length */
  246.    vfleng = (end - start + 1) >> 1;                /* voicing frame length */
  247.  
  248.    vfeatures(speech+start+vfleng,   lpspeech+start+vfleng,   vfleng, pitch, fbuf+6);
  249.    vfeatures(speech+start+2*vfleng, lpspeech+start+2*vfleng, vfleng, pitch, fbuf+9);
  250.  
  251.    /* make the voicing classification for the first half frame */
  252.    *v1 = *v2 = 0;
  253.    vclass = classify(fbuf);
  254.    if (vclass >= 0.0) *v1 = 1;
  255.  
  256.    /* make the voicing classification for the second half frame */
  257.    vclass = classify(fbuf+NFEATURE);
  258.    if (vclass >= 0.0) *v2 = 1;
  259. }
  260.